package com.xcw.utils.xml;



import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.converts.MySqlTypeConvert;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
import com.baomidou.mybatisplus.generator.config.rules.IColumnType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class MyBatisPlusGenerator {

    // ================= 自定义配置  =================

    /**
     * 需要生成的表名
     */
    private static final String[] tables = new String[]{"users"};

    /**
     * 数据源配置
     */
    private static final DbType DB_TYPE = DbType.MYSQL;
    private static final String JDBC_URL = "jdbc:mysql://localhost:3306/fmmail?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&serverTimezone=Asia/Shanghai&useSSL=false";
    private static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
    private static final String JDBC_USERNAME = "root";
    private static final String JDBC_PASSWORD = "123456";
    /**
     * 生成文件根目录及包名
     */
    private static final String SRC_ROOT_DIR ="mapper/src/main/java";
    private static final String SRC_PACKAGE_PARENT_NAME = "com.xcw.dao";
    private static final String RESOURCES_DIR ="mapper/src/main/resources";
    private static final String RESOURCES_PACKAGE_PARENT_NAME = "com.xcw.dao.mapper";

    public static void main(String[] args) {
        // 1. 全局配置
        GlobalConfig config = new GlobalConfig();
        config.setActiveRecord(false)  // 是否支持AR模式
                // 作者
                .setAuthor("admin")
                // 生成文件所在项目路径
                .setOutputDir(SRC_ROOT_DIR)
                // 是否覆盖文件
                .setFileOverride(true)
                .setEnableCache(false)
                // 主键策略
                .setIdType(IdType.AUTO)
                // 生成后是否打开文件夹
                .setOpen(false)
                // 开启实体属性Swagger2注解
                .setSwagger2(true)
                // XML二级缓存
                .setEnableCache(false)
                // 设置日期格式
                .setDateType(DateType.ONLY_DATE)
                // 自定义生成的类名
                .setMapperName("%sMapper")
                .setXmlName("%sMapper")
                .setServiceName("%sService")
                .setServiceImplName("%sServiceImpl")
                .setControllerName("%sController")
                // XML映射文件中是否生成基本的 resultMap
                .setBaseResultMap(true)
                // XML映射文件中是否生成基本的 columList
                .setBaseColumnList(true);

        //2. 配置自定义模板
        TemplateConfig tcConfig = new TemplateConfig();
        tcConfig.setController(null)
                .setService(null)
                .setServiceImpl(null)
                .setXml(null);

        // XML文件配置
        InjectionConfig cfgConfig = new InjectionConfig() {
            @Override
            public void initMap() {
                Map<String, Object> map = new HashMap<String, Object>();
                //map.put("abc", this.getConfig().getGlobalConfig().getAuthor() + "-rb");
                this.setMap(map);
            }
        };
        // XML生成路径
        List<FileOutConfig> focList = new ArrayList<>();
        // 如果模板引擎是velocity
        // String templatePath = "/templates/mapper.xml.vm";
        focList.add(new FileOutConfig("/templates/mapper.xml.vm") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                return RESOURCES_DIR + "/" + RESOURCES_PACKAGE_PARENT_NAME + "/" + tableInfo.getEntityName() + "Mapper.xml";
            }
        });
        cfgConfig.setFileOutConfigList(focList);

        // 3. 数据源配置
        DataSourceConfig dsConfig = new DataSourceConfig();
        dsConfig.setDbType(DB_TYPE)  // 设置数据库类型
                .setDriverName(JDBC_DRIVER)
                .setUrl(JDBC_URL)
                .setUsername(JDBC_USERNAME)
                .setPassword(JDBC_PASSWORD)
                .setTypeConvert(new MySqlTypeConvertCustom());

        // 4. 策略配置globalConfiguration中
        StrategyConfig stConfig = new StrategyConfig();
        stConfig.setCapitalMode(true)  // 全局大写命名
                // 数据库表映射到实体的命名策略，驼峰式命名映射
                .setNaming(NamingStrategy.underline_to_camel)
                // 是否使用 lombok 注解
                .setEntityLombokModel(true)
                // controller设置rest风格
                .setRestControllerStyle(true)
                //url中驼峰转连字符
                .setControllerMappingHyphenStyle(true)
                // 默认false 注释
                .setEntityTableFieldAnnotationEnable(true)
                // 需要生成的表, 支持多表一起生成，以数组形式填写
                .setInclude(tables);

        // 5. 包名策略配置
        PackageConfig pkConfig = new PackageConfig();
        pkConfig.setParent(SRC_PACKAGE_PARENT_NAME) // 设置包路径
                .setMapper("mapper")
                .setService("service")
                .setController("controller")
                .setEntity("model")
                .setXml("mapper");

        // 6. 整合配置
        AutoGenerator mpg = new AutoGenerator();
        mpg.setGlobalConfig(config)
                .setDataSource(dsConfig)
                .setStrategy(stConfig)
                .setPackageInfo(pkConfig)
                .setTemplate(tcConfig)
                .setCfg(cfgConfig);

        // 7. 执行
        mpg.execute();
        System.out.println("======= 代码生成完毕 ========");
    }
}

/**
 * 自定义类型转换
 */
class MySqlTypeConvertCustom extends MySqlTypeConvert implements ITypeConvert {
    @Override
    public IColumnType processTypeConvert(GlobalConfig globalConfig, String fieldType) {
        String t = fieldType.toLowerCase();
        if (t.contains("tinyint(1)")) {
            return DbColumnType.INTEGER;
        }
        return super.processTypeConvert(globalConfig, fieldType);
    }
}
